﻿using UnityEngine;

namespace UnityModule
{
    /// <summary>
    /// 单例类型
    /// </summary>
    public enum SingletonBehaviourType
    {
        //全局的,不销毁的
        GlobalInstance,

        //转场景销毁的
        PerSceneInstance,
    }


    /// <summary>
    /// 非线程安全 大部分情况请用这个,牵涉到多线程处理请用线程安全版本SingletonBehaviourSafe
    /// 如果不需要继承MonoBehaviour请不要使用该类型 请使用Singleton 或 SingletonSafe
    /// 注意:如果要设置单例类型,请在你的构造函数操作,且不要修改
    /// </summary>

    /// unity3d 继承MonoBehaviour请不要使用构造函数
    public class SingletonBehaviour<T> : MonoBehaviour where T : MonoBehaviour
    {
        private static T s_Instance;
        private SingletonBehaviourType _singletonType = SingletonBehaviourType.GlobalInstance;
        protected static bool s_bApplicationQuit { get; private set; } = false;

        /// <summary>
        /// 只能在构造函数里调用
        /// </summary>
        protected SingletonBehaviourType SingletonType
        {
            set
            {
                _singletonType = value;
            }
        }

        protected virtual void U3D_Constructed()
        {

        }

        /// <summary>
        /// 子类如果要用Awake
        /// 请:
        /// protected override  void Awake()
        /// {
        ///     base.Awake();
        ///     
        ///     your code
        /// }
        /// </summary>
        protected virtual void Awake()
        {
            U3D_Constructed();
#if UNITY_EDITOR
            if (FindObjectsOfType(typeof(T)).Length > 1)
            {
                P.E("场景中有多个相同单例对象,可能是手动拖上的,请检查:" + typeof(T).Name);
            }
#endif
            if (_singletonType == SingletonBehaviourType.GlobalInstance)
            {
                DontDestroyOnLoad(transform.root);
            }
        }

        public static T Instance
        {
            get
            {
                if (null == s_Instance && !s_bApplicationQuit)
                {
                    s_Instance = (T)Object.FindObjectOfType(typeof(T));
                    if (null == s_Instance)
                    {
                        GameObject singleton = new GameObject();
                        s_Instance = singleton.AddComponent<T>();
                        singleton.name = "(singleton) " + typeof(T).Name;
                    }
                }
                return s_Instance;
            }
        }

        public void OnApplicationQuit()
        {
            s_bApplicationQuit = true;
        }

    }



    /// <summary>
    /// 线程安全版本SingletonBehaviourSafe 单例   非线程安全用 SingletonBehaviour
    /// 如果不需要继承MonoBehaviour请不要使用该类型 请使用Singleton 或 SingletonSafe
    /// 注意:如果要设置单例类型,请在你的构造函数操作,且不要修改
    /// </summary>
    public class SingletonBehaviourSafe<T> : MonoBehaviour where T : MonoBehaviour
    {
        private static volatile T _instance;
        private static bool s_bApplicationIsQuitting = false;
        private static object _lock = new object();
        private SingletonBehaviourType _singletonType = SingletonBehaviourType.GlobalInstance;


        /// <summary>
        /// 只能在构造函数里调用
        /// </summary>
        protected SingletonBehaviourType SingletonType
        {
            set
            {
                _singletonType = value;
            }
        }

        /// <summary>
        /// 子类如果要用Awake
        /// 请:
        /// protected override  void Awake()
        /// {
        ///     base.Awake();
        ///     
        ///     your code
        /// }
        /// </summary>
        protected virtual void Awake()
        {
            _instance = this as T;
            U3D_Constructed();
#if UNITY_EDITOR
            if (FindObjectsOfType(typeof(T)).Length > 1)
            {
                P.D("场景中有多个相同单例对象,可能是手动拖上的,请检查:" + typeof(T).Name);
            }
#endif
            if (_singletonType == SingletonBehaviourType.GlobalInstance)
            {
                DontDestroyOnLoad(transform.root);
            }
        }



        protected virtual void U3D_Constructed()
        {

        }

        public static T Instance
        {
            get
            {
                if (s_bApplicationIsQuitting)
                    return null;
                if(null == _instance)
                {
                    lock (_lock)
                    {
                        if (null == _instance)
                        {
                            _instance = (T)Object.FindObjectOfType(typeof(T));
                            if (null == _instance)
                            {
                                GameObject singleton = new GameObject();
                                singleton.AddComponent<T>();
                                singleton.name = "(singleton) " + typeof(T).Name;
                            }
                        }
#if UNITY_EDITOR
                        if (FindObjectsOfType(typeof(T)).Length > 1)
                        {
                            P.D("场景中有多个相同单例对象,可能是手动拖上的,请检查:" + typeof(T).Name);
                        }
#endif
                    }
                }
                return _instance;
            }
        }
        public void OnApplicationQuit()
        {
            s_bApplicationIsQuitting = true;
        }
    }


}


//例 wending 不要写构造函数继承MonoBehaviour的类注意

//using ModuleBase.Utility;
//public class ForTest : SingletonBehaviour<ForTest>
//{
//    protected override void Awake()
//    {
//        base.Awake();
//        //你的代码
//    }

//如果你要改类型
//        SingletonType = SingletonBehaviourType.PerSceneInstance;

//    protected override void U3D_Constructed()
//    {
//        SingletonType = SingletonBehaviourType.PerSceneInstance;
//    }

//    //不要这样做, unity编辑器原因会多次执行
//    protected ForTest()
//    {
//        SingletonType = SingletonBehaviourType.PerSceneInstance;
//    }
//}



